// /////////////////////////////////////////////////////////////////////////////
//
// Name:            AIFrame.h
// Author:          Michael Bartsch
//
// Desc :           This file contains the CAIFrame Class. This class
//                  contains the AI Control which can be used to control
//                  with the integrated Artificial Intelligent Core.
//
// License:         Copyright (C) 2008-2009 Michael Bartsch
//
//                  This program is free software: you can redistribute it
//                  and/or modify it under the terms of the GNU General Public
//                  License as published by the Free Software Foundation,
//                  either version 3 of the License, or (at your option) any
//                  later version.
//
//                  This program is distributed in the hope that it will be
//                  useful, but WITHOUT ANY WARRANTY; without even the implied
//                  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
//                  PURPOSE. See the GNU General Public License for more
//                  details.
//
//                  You should have received a copy of the GNU General Public
//                  License along with this program. If not, see
//                  <http://www.gnu.org/licenses/>.
//
// /////////////////////////////////////////////////////////////////////////////

// Include required header file(s).
#include "AIFrame.h"


// CAIFrame Events. - [ BEGIN ]
BEGIN_EVENT_TABLE(CAIFrame, wxFrame)
   EVT_CLOSE(CAIFrame::onClose)

   EVT_MENU(wxID_NEW,               CAIFrame::onReset)
   EVT_MENU(wxID_EXIT,              CAIFrame::onQuit)

   EVT_COMBOBOX(AIF_TB_State,  CAIFrame::onStateSelector)
   EVT_RADIOBOX(AIF_StateBox,       CAIFrame::onAgentState)
   EVT_SPINCTRL(AIF_StartX,         CAIFrame::onStartX)
   EVT_SPINCTRL(AIF_StartY,         CAIFrame::onStartY)
   EVT_CHECKBOX(AIF_EnableTarget,   CAIFrame::onEnableTarget)
   EVT_SPINCTRL(AIF_TargetX,        CAIFrame::onTargetX)
   EVT_SPINCTRL(AIF_TargetY,        CAIFrame::onTargetX)
END_EVENT_TABLE()
// CAIFrame Events. - [ END ]


// CAIFrame.
// Constructor.
CAIFrame::CAIFrame(wxWindow *parent)
: wxFrame(parent, wxID_ANY, _T("Aia|CP - AI Control"), wxPoint(0,0), wxSize(1024,768), wxDEFAULT_FRAME_STYLE & ~ (wxRESIZE_BORDER | wxRESIZE_BOX | wxMAXIMIZE_BOX))
{
   // Set internal variables.
   frameParent = (CMainFrame*)parent;
   pAICore = CAICore::Instance();

   // Tell wxAuiManager to manage this frame.
   frameManager.SetManagedWindow(this);
   frameManager.SetFlags(wxAUI_MGR_DEFAULT & ~ wxAUI_MGR_ALLOW_FLOATING);

   // Init the Menubar.
   wxMenuBar* menuBar = new wxMenuBar();

   // Menu->File Menu
   wxMenu *fileMenu = new wxMenu;

   wxMenuItem *fmReset = new wxMenuItem(fileMenu, wxID_NEW, _T("&Reset\tCtrl+R"), _T("Resets the AI Core"));
   fmReset->SetBitmap(wxIcon("../media/file-new.png", wxBITMAP_TYPE_PNG));

   wxMenuItem *fmQuit = new wxMenuItem(fileMenu, wxID_EXIT, _T("&Quit\tCtrl+Q"), _T("Exit Aia|CP"));
   fmQuit->SetBitmap(wxIcon("../media/file-quit.png", wxBITMAP_TYPE_PNG));

   fileMenu->Append(fmReset);
   fileMenu->AppendSeparator();
   fileMenu->Append(fmQuit);

   // Add submenu's to the Menu Bar.
   menuBar->Append(fileMenu, _T("&File"));

   // Associate the Menu Bar with the frame.
   SetMenuBar(menuBar);

   // Init the Toolbar.
   wxToolBar *toolBar = CreateToolBar(wxTB_FLAT | wxNO_BORDER | wxTB_HORIZONTAL, -1);

   toolBar->AddTool(wxID_NEW, _T("Reset"), wxBitmap("../media/file-new.png", wxBITMAP_TYPE_PNG), _T("Resets the AI Core"));
   toolBar->AddSeparator();

   // Toolbar->State Selector
   wxString *stateStrings = new wxString[5];
   stateStrings[0] = "Start";
   stateStrings[1] = "Target";
   stateStrings[2] = "Walkable";
   stateStrings[3] = "Unwalkable";
   stateStrings[4] = "Unknown";

   wxBitmapComboBox *stateSelector = new wxBitmapComboBox(toolBar, AIF_TB_State, _T("Start"), wxDefaultPosition, wxDefaultSize, 5, stateStrings, wxCB_READONLY);
   toolBar->AddControl(stateSelector);

   delete [] stateStrings;
   toolBar->Realize();

   // Init the Status Bar.
   wxStatusBar *statusBar = CreateStatusBar(3, 0, -1);

   int *IntArray = new int[3];
   IntArray[0] = -3;   IntArray[1] = -1; IntArray[2] = -1;
   statusBar->SetStatusWidths(3, IntArray);
   delete[] IntArray;

   // Create the frame panes.
   // AI Pane
   aiPane = new CAIPanel(this);

   // Settings Pane
   wxPanel *settingsPanel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(246,562));
   wxSizer *settingsSizer = new wxBoxSizer(wxVERTICAL);

   // Settings Pane->Agent State
   wxPanel *statePanel = new wxPanel(settingsPanel, wxID_ANY);
   wxSizer *stateSizer = new wxStaticBoxSizer(wxVERTICAL, statePanel, _T("Agent State"));

   // Settings Pane->Agent State->Radiobox
   stateStrings = new wxString[2];
   stateStrings[0] = "Off";
   stateStrings[1] = "Target State";

   stateBox = new wxRadioBox(statePanel, AIF_StateBox, _T(""), wxDefaultPosition, wxDefaultSize, 2, stateStrings);
   stateBox->SetSelection(pAICore->getAgentState());

   stateSizer->Add(stateBox, wxSizerFlags(3).Expand());

   // Settings Pane->Agent State->Set sizer.
   statePanel->SetSizer(stateSizer);
   stateSizer->SetSizeHints(statePanel);

   // Settings Pane->Start Position
   wxPanel *startPosPanel = new wxPanel(settingsPanel, wxID_ANY);
   wxSizer *startPosSizer = new wxStaticBoxSizer(wxVERTICAL, startPosPanel, _T("Start Position"));

   // Settings Pane->Start Position->X
   wxSizer *tempSizer = new wxBoxSizer(wxHORIZONTAL);
   wxString tempString;

   tempSizer->Add(new wxStaticText(startPosPanel, wxID_ANY, wxT("X:")), wxSizerFlags(1).Expand().Border(wxTOP | wxRIGHT, 3));

   tempString.Clear();
   tempString.Printf(wxT("%d"), (int)pAICore->getStartX());
   startX = new wxSpinCtrl(startPosPanel, AIF_StartX, tempString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 99, 0);
   tempSizer->Add(startX, wxSizerFlags(3).Expand());

   startPosSizer->Add(tempSizer, wxSizerFlags().Expand().Border(wxTOP, 2));

   // Settings Pane->Start Position->Y
   tempSizer = new wxBoxSizer(wxHORIZONTAL);
   tempSizer->Add(new wxStaticText(startPosPanel, wxID_ANY, wxT("Y:")), wxSizerFlags(1).Expand().Border(wxTOP | wxRIGHT, 3));

   tempString.Clear();
   tempString.Printf(wxT("%d"), (int)pAICore->getStartY());
   startY = new wxSpinCtrl(startPosPanel, AIF_StartY, tempString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 99, 0);
   tempSizer->Add(startY, wxSizerFlags(3).Expand());

   startPosSizer->Add(tempSizer, wxSizerFlags().Expand().Border(wxTOP, 2));

   // Settings Pane->Start Position->Set sizer.
   startPosPanel->SetSizer(startPosSizer);
   startPosSizer->SetSizeHints(startPosPanel);

   // Settings Pane->Target Position
   wxPanel *targetPosPanel = new wxPanel(settingsPanel, wxID_ANY);
   wxSizer *targetPosSizer = new wxStaticBoxSizer(wxVERTICAL, targetPosPanel, _T("Target Position"));

   // Settings Pane->Enable Target
   enableTarget = new wxCheckBox(targetPosPanel, AIF_EnableTarget, wxT("Enable target"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE);
   targetPosSizer->Add(enableTarget, wxSizerFlags().Expand().Border(wxTOP, 2));

   if(pAICore->getIsTarget())
      enableTarget->SetValue(true);

   else enableTarget->SetValue(false);

   // Settings Pane->Target Position->X
   tempSizer = new wxBoxSizer(wxHORIZONTAL);
   tempSizer->Add(new wxStaticText(targetPosPanel, wxID_ANY, wxT("X:")), wxSizerFlags(1).Expand().Border(wxTOP | wxRIGHT, 3));

   tempString.Clear();
   tempString.Printf(wxT("%d"), (int)pAICore->getTargetX());
   targetX = new wxSpinCtrl(targetPosPanel, AIF_TargetX, tempString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 99, 0);
   tempSizer->Add(targetX, wxSizerFlags(3).Expand());

   targetPosSizer->Add(tempSizer, wxSizerFlags().Expand().Border(wxTOP, 2));

   // Settings Pane->Target Position->Y
   tempSizer = new wxBoxSizer(wxHORIZONTAL);
   tempSizer->Add(new wxStaticText(targetPosPanel, wxID_ANY, wxT("Y:")), wxSizerFlags(1).Expand().Border(wxTOP | wxRIGHT, 3));

   tempString.Clear();
   tempString.Printf(wxT("%d"), (int)pAICore->getTargetY());
   targetY = new wxSpinCtrl(targetPosPanel, AIF_TargetY, tempString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 99, 0);
   tempSizer->Add(targetY, wxSizerFlags(3).Expand());

   targetPosSizer->Add(tempSizer, wxSizerFlags().Expand().Border(wxTOP, 2));

   // Settings Pane->Target Position->Set sizer.
   targetPosPanel->SetSizer(targetPosSizer);
   targetPosSizer->SetSizeHints(targetPosPanel);

   // Set the main sizer.
   settingsSizer->Add(statePanel, wxSizerFlags().Expand().Border(wxALL, 3));
   settingsSizer->Add(startPosPanel, wxSizerFlags().Expand().Border(wxALL, 3));
   settingsSizer->Add(targetPosPanel, wxSizerFlags().Expand().Border(wxALL, 3));

   settingsPanel->SetSizer(settingsSizer);
   settingsSizer->SetSizeHints(settingsPanel);

   // Add the panes.
   frameManager.AddPane(aiPane, wxAuiPaneInfo().Name(wxT("paneAI")).
                        CaptionVisible(false).Center().Layer(1).Position(1).
                        CloseButton(false).Resizable(false).MinSize(wxSize(768,560)));

   frameManager.AddPane(settingsPanel, wxAuiPaneInfo().Name(wxT("paneSettings")).
                        Caption(wxT("Settings")).Right().Layer(1).Position(1).
                        CloseButton(false).Resizable(false).MinSize(wxSize(246,560)));

   frameManager.Update();
}

// Updates the frame.
void CAIFrame::update()
{
   stateBox->SetSelection(pAICore->getAgentState());

   startX->SetValue(pAICore->getStartX());
   startY->SetValue(pAICore->getStartY());

   enableTarget->SetValue(pAICore->getIsTarget());
   targetX->SetValue(pAICore->getTargetX());
   targetY->SetValue(pAICore->getTargetY());

   aiPane->updateBuffer();
}

// Event Functions. - [ BEGIN ]
void CAIFrame::onClose(wxCloseEvent &event)
{
   // Deinitialise wxAuiManager.
   frameManager.UnInit();

   // Reset the frame state.
   frameParent->resetAIFrame();

   // Destroy the frame.
   Destroy();
}

void CAIFrame::onReset(wxCommandEvent &event)
{
   pAICore->setStartX(50);
   pAICore->setStartY(50);
   pAICore->setTargetX(50);
   pAICore->setTargetY(49);

   pAICore->setAgentState(0);
   pAICore->setIsTarget(false);
   pAICore->resetMap();

   update();
}

void CAIFrame::onQuit(wxCommandEvent &event)
{
   Close(true);
}

void CAIFrame::onStateSelector(wxCommandEvent &event)
{
   aiPane->setState(event.GetSelection());
}

void CAIFrame::onAgentState(wxCommandEvent &event)
{
   pAICore->setAgentState(event.GetSelection());
}

void CAIFrame::onStartX(wxSpinEvent &event)
{
   pAICore->setStartX(event.GetPosition());
   aiPane->updateBuffer();
}

void CAIFrame::onStartY(wxSpinEvent &event)
{
   pAICore->setStartY(event.GetPosition());
   aiPane->updateBuffer();
}

void CAIFrame::onEnableTarget(wxCommandEvent &event)
{
   pAICore->setIsTarget(event.IsChecked());
}

void CAIFrame::onTargetX(wxSpinEvent &event)
{
   pAICore->setTargetX(event.GetPosition());
   aiPane->updateBuffer();
}

void CAIFrame::onTargetY(wxSpinEvent &event)
{
   pAICore->setTargetY(event.GetPosition());
   aiPane->updateBuffer();
}
// Event Functions. - [ END ]

// End of File

